﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.ComponentModel;

namespace Elentok.Common.Wpf
{
  /// <summary>
  /// This command can listen to PropertyChanged events
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public class ListeningCommand<T>
    : DelegateCommand<T>
  {
    /// <summary>
    /// Initializes a new instance of the <see cref="ListeningCommand&lt;T&gt;"/> class
    /// </summary>
    /// <param name="executeMethod"></param>
    /// <param name="canExecuteMethod"></param>
    /// <param name="objectToListenTo"></param>
    /// <param name="propertiesToListenTo">
    /// Which properties should raise the "CanExecuteChanged" event
    /// (leave empty for all properties)
    /// </param>
    public ListeningCommand(Action<T> executeMethod,
      Func<T,bool> canExecuteMethod,
      INotifyPropertyChanged objectToListenTo,
      params string[] propertiesToListenTo)
      : base(executeMethod, canExecuteMethod)
    {
      if (objectToListenTo != null)
        Listen(objectToListenTo, propertiesToListenTo);
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="ListeningCommand&lt;T&gt;"/> class
    /// </summary>
    /// <param name="executeMethod"></param>
    /// <param name="canExecuteMethod"></param>
    public ListeningCommand(Action<T> executeMethod,
      Func<T, bool> canExecuteMethod)
      : this(executeMethod, canExecuteMethod, null) { }

    /// <summary>
    /// Listen to an object's PropertyChanged event 
    /// </summary>
    /// <param name="objectToListenTo"></param>
    /// <param name="propertiesToListenTo">
    /// Which properties should raise the "CanExecuteChanged" event
    /// (leave empty for all properties)
    /// </param>
    public void Listen(INotifyPropertyChanged objectToListenTo,
      params string[] propertiesToListenTo)
    {
      if (objectToListenTo == null)
        throw new ArgumentNullException("objectToListenTo");

      objectToListenTo.PropertyChanged += (o, e) =>
        {
          if ((propertiesToListenTo.Length == 0) ||
              ((Array.IndexOf(propertiesToListenTo, e.PropertyName)) != -1))
            RaiseCanExecuteChanged();
        };
    }
  }
}
